/*
	Script: utils.js
		Foo - Framework for Rapid RIA Development

	License:
		MIT-style license.

	Foo Copyright:
		Copyright (c) 2007 Rizqi Ahmad, <http://riiv.net>

	Foo Credits:
		- Uses prototype.js <http://prototype.conio.net/> (c) 2005 Sam Stephenson sam [at] conio [dot] net, MIT-style license
		- Documentation by Rizqi Ahmad (raid_ox [at] yahoo [dot] de).
*/

// Utilities
foo.Utils = {
	replace: function(text, reps){
		var result = '', nr, ioNr, ioI;
		while(text){
			for(var i=0; i<reps.length; i++){
				if(typeof nr != 'number' || text.indexOf(reps[nr][0]) == -1)
					nr = i;
					
				ioNr = text.indexOf(reps[nr][0]);
				ioI = text.indexOf(reps[i][0]);
				
				if(ioI != -1 && ioNr > ioI){
					nr = i;
					ioNr = ioI;
				}
			}
			if(ioNr != -1){
				result += text.substring(0, ioNr)+reps[nr][1];
				text = text.substring(ioNr+reps[nr][0].length, text.length);
			}else{
				result += text;
				text = '';
			}
		}
		return result;
	},
	
	serializeTag: function(node, closer){
		var tag, attr, attributes = [];
		var autoclose = ['img', 'br'].include(node.nodeName.toLowerCase());
		if(foo.Browser.IE){
			tag = node.outerHTML.substring(node.outerHTML.indexOf('<'+node.nodeName)+1, node.outerHTML.indexOf('>'));
			tag = foo.Utils.replace(tag, foo.entityChars);
		}else{
			var attrs = $A(node.attributes);
			if(foo.reversion)
				attrs = attrs.reverse();
			attrs.each(function(attr){
				if(attr.nodeValue != null && attr.nodeValue != '')
					attributes.push(' ' + attr.nodeName + '=' + (typeof attr.nodeValue == 'string' && attr.nodeValue.indexOf('"') > -1 ? "'"+attr.nodeValue+"'" : '"'+attr.nodeValue+'"'));
			})
			attributes = foo.Utils.replace(attributes.join(''), foo.entityChars);
		}
		if(closer)
			return !autoclose ? '</'+(tag ? node.nodeName : node.nodeName.toLowerCase())+'>' : '';
		else
			return '<'+ (tag || node.nodeName.toLowerCase()+attributes) + (autoclose ? ' /' : '')+'>';
	},
	
	reverseTest: function(){
		var div, container = document.createElement('div');
		container.innerHTML = '<div att1="1" att2="2"></div>';
		
		for(var i=0; i<container.childNodes.length; i++){
			if(container.childNodes[i].nodeName.toLowerCase() == 'div')
				div = container.childNodes[i];
			break;
		}
		
		for(var i=0; i<div.attributes.length; i++)
			if(div.attributes[i].nodeName.toLowerCase() == 'att1')
				return false;
			else if(div.attributes[i].nodeName.toLowerCase() == 'att2')
				return true;
	},
	
	notateAttributes: function(node){
		var attr = $A(node.attributes).select(function(e){return !!e.nodeValue;});
		var obj = {};
		attr.each(function(e,i,s){
			var value = {};
			value.toJSON = function(){return foo.parseInline(e.nodeValue);};
			obj[e.nodeName] = value;
		});
		return obj;
	},
	
	serialize: function(obj){
		if(obj instanceof Array){
			return '['+obj.map(foo.Utils.serialize).join(', ')+']';
		}else if(typeof obj == 'object'){
			var res = $H(obj);
			res = res.map(function(e){
				return foo.Utils.serialize(e.key)+': '+foo.Utils.serialize(e.value);
			});
			return '{'+res.join(', ')+'}';
		}else if(typeof obj == 'string'){
			return obj.toJSON();
		}else if(typeof obj == 'function'){
			return obj.toString().replace(/^function anonymous/, 'function');
		}else if(obj == null){
			return 'null';
		}else if(obj.toString){
			return obj.toString();
		}
	},
	
	convertXMLToJSON: function(xml) {
		var result;
		if(xml.childNodes && xml.childNodes.length == 0){
			result = null;
		}
		else if(xml.childNodes && xml.childNodes.length == 1 && xml.childNodes[0].nodeName == "#text") {
			result = xml.childNodes[0].nodeValue;
		}else if(xml.documentElement){
			result = {};
			result[xml.documentElement.nodeName] = foo.Utils.convertXMLToJSON(xml.documentElement);
		}else{
			result = {};
			for(var i=0; i<xml.childNodes.length; i++) {
				if(result[xml.childNodes[i].nodeName]) {
					if(!(result[xml.childNodes[i].nodeName] instanceof Array))
						result[xml.childNodes[i].nodeName] = [result[xml.childNodes[i].nodeName]];
					result[xml.childNodes[i].nodeName].push(foo.Utils.convertXMLToJSON(xml.childNodes[i]));
				}else if(xml.childNodes[i].nodeName.indexOf('#') == -1)
					result[xml.childNodes[i].nodeName] = foo.Utils.convertXMLToJSON(xml.childNodes[i]);
			}
		}
		
		if(xml.attributes)
			for(var i=0; i<xml.attributes.length; i++)
				result['@'+xml.attributes[i].nodeName] = xml.attributes[i].nodeValue;
		
		return result;
	},
	
	alterTree: function(tree, path, fn) {
		var obj = tree;
		path = path.split('.');
		for(var i=0; i<path.length-1; i++) {
			if(obj[path[i]])
				obj = obj[path[i]];
			else
				return;
		}
		obj[path[path.length-1]] = fn(obj[path[path.length-1]]);
	},

	followPath: function(obj, path){
		path = path.split('.');
		for(var i=0; i<path.length; i++) {
			if(obj[path[i]])
				obj = obj[path[i]];
			else
				return false;
		}
		return obj;
	}
};